package uk.ac.aber.Blockmation;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import uk.ac.aber.Blockmation.Actions.ActionPlayMovieViewer;

/**
 * Displays animations from a movieModel, can also be separated from main application
 * @author alex
 */

public class Viewer extends JFrame implements ItemListener, ComponentListener {
	
    protected MovieModel movieModel;
    private Display display;
    
    private JPanel controlPanel;
    private JComboBox speedSelector;
    private JCheckBox loopCheckBox;
    
    private Boolean loop;
    
    private int speed;
    private String[] speeds;
    private String currentSpeedFPS;

    
    Viewer(MovieModel movieModel) {
        
        this.setTitle("Animation Viewer - GIFted Blockmation");
        //this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setAlwaysOnTop(true);
        this.movieModel = movieModel;
        display = new Display();
        
        speeds =  new String[]{"1", "2", "5", "10", "20", "25"};

        this.addComponentListener(this);
        
        updateNewModel(movieModel);
        //createGUI();
        
        // Add Display to Frame
        this.getContentPane().add(display, BorderLayout.CENTER);

    }
    
    
    /**
     * Method creates the components for the Viewer and adds them to the JFrame
     */
    protected void createGUI () {

        // Create Control Panel  //
        controlPanel = new JPanel();
        
        // Create Speed Selector
        JLabel speedLabel = new JLabel("Set Speed (FPS) ");
        speedSelector = new JComboBox(speeds);
        speedSelector.addItemListener(this);
        
        // Set SpeedSelector value to actual value
        for (int i = 0; i < speeds.length-1; i++) {
            if (speeds[i].equals(currentSpeedFPS.toString())) {
                speedSelector.setSelectedIndex(i);
            }
        }
        
        
        // Create Loop checkbox
        JLabel loopLabel = new JLabel("Loop");
        loopCheckBox = new JCheckBox();
        loopCheckBox.addItemListener(this);
        
        // Create Play animation button
        AbstractAction actionPlayMovieViewer = new ActionPlayMovieViewer(this);
        JButton playMovie = new JButton(actionPlayMovieViewer);
        
        // Set Layout for components
        FlowLayout flowLayout = new FlowLayout(0,10,10);
        controlPanel.setLayout(flowLayout);
        
        // Add all the components to the JPanel
        controlPanel.add(speedLabel);
        controlPanel.add(speedSelector);
        controlPanel.add(loopLabel);
        controlPanel.add(loopCheckBox);
        controlPanel.add(playMovie);
        
        this.getContentPane().add(controlPanel, BorderLayout.SOUTH);
    }
    
    
    /**
     * Updates the viewers instance of the movieModel with that of the one from
     * mainFrame, or the stand alone class.
     */
    public void updateNewModel(MovieModel movieModel) {
        
        this.movieModel = movieModel;
        
        // set display to show first frame before animation starts
        try {
            display.setImage(movieModel.get(0));
        } catch (ArrayIndexOutOfBoundsException e) {
            
        }
        
        speed = movieModel.getSpeed();
        currentSpeedFPS =  ""+(1000/speed);
        
        loop = false;
        
    }
    
    /**
     * Returns movieModel object so the playMovieThread is consistent with the
     * the current model incase a new project is loaded
     */
    public MovieModel getMovieModel() {
        return this.movieModel;
    }
    
    /**
     * Returns the display object for the playMovieThread to write the output of
     * the frame to
     */
    public Display getDisplay() {
        return this.display;
    }
    
    /**
     * Returns the internal speed variable for the Viewer class
     */
    public int getSpeed() {
        return speed;
    }
    
    /**
     * Returns whether loop is set or not
     */
    public boolean getLoop() {
        return loop;
    }
    
    /**
     * Method for setting the new speed of the animation from the drop down menu
     */
    public void itemStateChanged(ItemEvent event) {
        
        Object source = event.getItemSelectable();
        
        if (source == speedSelector) {
            
            String choice = (String)event.getItem();
            int speedTemp = Integer.parseInt(choice);

            speed = 1000 / speedTemp;
            
        } else if (source == loopCheckBox) {
            
            if (event.getStateChange() == ItemEvent.SELECTED) {
                loop = true;
            } else {
                loop = false;
            }
            
        }
        
        
    }

    /**
     * Method sets a new blocksize when the window has been resized, which scales
     * the animation to the new dimension
     */
    public void componentResized(ComponentEvent e) {
        
        int availWidth = this.getWidth();
        int availHeight = this.getHeight();

        int frameWidth = display.getImage().getWidth();
        int frameHeight = display.getImage().getHeight();

        int newSize;

        newSize = (int)Math.min((availWidth/frameWidth), (availHeight / frameHeight));

        display.setBlockSize(new Dimension(newSize, newSize));
        
        this.pack();
        
    }
    
    /**
     * When the Viewer is closed, the thread is stopped by setting loop to false
     * as this will preserve cpu and memory
     */
    public void componentHidden(ComponentEvent e) {
        loop = false;
        loopCheckBox.setSelected(false);
    }

    public void componentMoved(ComponentEvent e) {}

    public void componentShown(ComponentEvent e) {}
    
    public void setDefaultSize() {
        this.setSize(400,400);
    }

}
